home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char *RCSid = "$Id: graph3d.c,v 1.85 1995/12/02 22:04:32 drd Exp $";
- #endif
-
-
- /* GNUPLOT - graph3d.c */
- /*
- * Copyright (C) 1986 - 1993 Thomas Williams, Colin Kelley
- *
- * Permission to use, copy, and distribute this software and its
- * documentation for any purpose with or without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation.
- *
- * Permission to modify the software is granted, but not the right to
- * distribute the modified code. Modifications are to be distributed
- * as patches to released version.
- *
- * This software is provided "as is" without express or implied warranty.
- *
- *
- * AUTHORS
- *
- * Original Software:
- * Gershon Elber and many others.
- *
- * 19 September 1992 Lawrence Crowl (crowl@cs.orst.edu)
- * Added user-specified bases for log scaling.
- *
- * 3.6 - split graph3d.c into graph3d.c (graph),
- * util3d.c (intersections, etc)
- * hidden3d.c (hidden-line removal code)
- *
- * There is a mailing list for gnuplot users. Note, however, that the
- * newsgroup
- * comp.graphics.gnuplot
- * is identical to the mailing list (they
- * both carry the same set of messages). We prefer that you read the
- * messages through that newsgroup, to subscribing to the mailing list.
- * (If you can read that newsgroup, and are already on the mailing list,
- * please send a message info-gnuplot-request@dartmouth.edu, asking to be
- * removed from the mailing list.)
- *
- * The address for mailing to list members is
- * info-gnuplot@dartmouth.edu
- * and for mailing administrative requests is
- * info-gnuplot-request@dartmouth.edu
- * The mailing list for bug reports is
- * bug-gnuplot@dartmouth.edu
- * The list of those interested in beta-test versions is
- * info-gnuplot-beta@dartmouth.edu
- */
-
- #include <math.h>
- #if !defined(sequent) && !defined(apollo) && !defined(alliant)
- #include <limits.h>
- #endif
- #include "plot.h"
- #include "setshow.h"
-
-
- #define KEYWTH ( (int) (4*(t->h_char) + pointsize*(t->h_tic)))
-
- extern TBOOLEAN term_graphics, term_suspended;
-
- static int p_height;
- static int p_width; /* pointsize * t->h_tic */
- static int key_entry_height; /* bigger of t->v_size, pointsize*t->v_tick */
-
- int suppressMove = 0; /* for preventing moveto while drawing contours */
-
- /*
- * hidden_line_type_above, hidden_line_type_below - controls type of lines
- * for above and below parts of the surface.
- * hidden_no_update - if TRUE lines will be hidden line removed but they
- * are not assumed to be part of the surface (i.e. grid) and therefore
- * do not influence the hidings.
- * hidden_active - TRUE if hidden lines are to be removed.
- */
- int hidden_active = FALSE;
-
- /* LITE defines a restricted memory version for MS-DOS, which doesn't
- * use the routines in hidden3d.c
- */
-
- #ifndef LITE
- int hidden_line_type_above, hidden_line_type_below;
- int hidden_no_update;
- #endif /* LITE */
-
-
- static double LogScale __P((double coord, TBOOLEAN is_log, double log_base_log,
- char *what, char *axis));
- static void plot3d_impulses __P((struct surface_points *plot));
- static void plot3d_lines __P((struct surface_points *plot));
- static void plot3d_points __P((struct surface_points *plot));
- static void plot3d_dots __P((struct surface_points *plot));
- static void cntr3d_impulses __P((struct gnuplot_contours *cntr, struct surface_points *plot));
- static void cntr3d_lines __P((struct gnuplot_contours *cntr));
- static void cntr3d_points __P((struct gnuplot_contours *cntr, struct surface_points *plot));
- static void cntr3d_dots __P((struct gnuplot_contours *cntr));
- static void check_corner_height __P((struct coordinate GPHUGE *point, double height[2][2], double depth[2][2]));
- static void draw_bottom_grid __P((struct surface_points *plot, int plot_count));
- static void xtick_callback __P((int axis, double place, char *text, int grid));
- static void ytick_callback __P((int axis, double place, char *text, int grid));
- static void ztick_callback __P((int axis, double place, char *text, int grid));
- static void setlinestyle __P((int style));
-
- static void boundary3d __P((int scaling, struct surface_points *plots, int count));
- #if 0 /* not used */
- static double dbl_raise __P((double x, int y));
- #endif
- static void map_position __P((struct position *pos, unsigned int *x, unsigned int *y, char *what));
-
- /* put entries in the key */
- static void key_sample_line __P((int xl, int yl));
- static void key_sample_point __P((int xl, int yl, int pointtype));
- static void key_text __P((int xl, int yl, char *text));
-
-
- #if defined(sun386) || defined(AMIGA_SC_6_1)
- static double CheckLog __P((TBOOLEAN is_log, double base_log, double x));
- #endif
-
-
- #ifndef max /* Lattice C has max() in math.h, but shouldn't! */
- #define max(a,b) ((a > b) ? a : b)
- #endif
-
- #ifndef min
- #define min(a,b) ((a < b) ? a : b)
- #endif
-
- /*
- * The Amiga SAS/C 6.2 compiler moans about macro envocations causing
- * multiple calls to functions. I converted these macros to inline
- * functions coping with the problem without loosing speed.
- * (MGR, 1993)
- */
- #ifdef AMIGA_SC_6_1
- __inline static TBOOLEAN i_inrange(int z,int min,int max)
- {
- return((min<max) ? ((z>=min)&&(z<=max)) : ((z>=max)&&(z<=min)));
- }
-
- __inline static double f_max(double a,double b)
- {
- return(max(a,b));
- }
-
- __inline static double f_min(double a,double b)
- {
- return(min(a,b));
- }
-
- #else
- #define f_max(a,b) max((a),(b))
- #define f_min(a,b) min((a),(b))
- #define i_inrange(z,a,b) inrange((z),(a),(b))
- #endif
-
- #define inrange(z,min,max) ((min<max) ? ((z>=min)&&(z<=max)) : ((z>=max)&&(z<=min)) )
-
- #define apx_eq(x,y) (fabs(x-y) < 0.001)
- #define ABS(x) ((x) >= 0 ? (x) : -(x))
- #define SQR(x) ((x) * (x))
-
- /* Define the boundary of the plot
- * These are computed at each call to do_plot, and are constant over
- * the period of one do_plot. They actually only change when the term
- * type changes and when the 'set size' factors change.
- */
-
- /* in order to allow graphic.c to use clip_draw_line, we must
- * share xleft, xright, ybot, ytop with graphics.c
- */
- extern int xleft, xright, ybot, ytop;
-
- int xmiddle, ymiddle, xscaler, yscaler;
- static int ptitl_cnt;
- static int max_ptitl_len;
- static int titlelin;
- static int key_rows, key_cols, key_col_wth, yl_ref;
- static int ktitle_lines = 0;
-
-
- /* Boundary and scale factors, in user coordinates */
- /* x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d are local to this
- * file and are not the same as variables of the same names in other files
- */
- /*static double x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d;*/
- /* sizes are now set in min_array[], max_array[] from command.c */
- extern double min_array[], max_array[];
- extern int auto_array[], log_array[];
- extern double base_array[], log_base_array[];
-
- /* for convenience while converting to use these arrays */
- #define x_min3d min_array[FIRST_X_AXIS]
- #define x_max3d max_array[FIRST_X_AXIS]
- #define y_min3d min_array[FIRST_Y_AXIS]
- #define y_max3d max_array[FIRST_Y_AXIS]
- #define z_min3d min_array[FIRST_Z_AXIS]
- #define z_max3d max_array[FIRST_Z_AXIS]
-
- /* There are several z's to take into account - I hope I get these
- * right !
- *
- * ceiling_z is the highest z in use
- * floor_z is the lowest z in use
- * base_z is the z of the base
- * min3d_z is the lowest z of the graph area
- * max3d_z is the highest z of the graph area
- *
- * ceiling_z is either max3d_z or base_z, and similarly for floor_z
- * There should be no part of graph drawn outside
- * min3d_z:max3d_z - apart from arrows, perhaps
- */
-
- double ceiling_z, floor_z, base_z;
-
- /* and some bodges while making the change */
- #define min3d_z min_array[FIRST_Z_AXIS]
- #define max3d_z max_array[FIRST_Z_AXIS]
-
-
- double xscale3d, yscale3d, zscale3d;
-
-
- typedef double transform_matrix[4][4];
- transform_matrix trans_mat;
-
- static double xaxis_y, yaxis_x, zaxis_x, zaxis_y;
-
- /* the co-ordinates of the back corner */
- static double back_x, back_y;
-
- /* the penalty for convenience of using tic_gen to make callbacks
- * to tick routines is that we cant pass parameters very easily.
- * We communicate with the tick_callbacks using static variables
- */
-
- /* unit vector (terminal coords) */
- static double tic_unitx, tic_unity;
-
- /* (DFK) Watch for cancellation error near zero on axes labels */
- #define SIGNIF (0.01) /* less than one hundredth of a tic mark */
- #define CheckZero(x,tic) (fabs(x) < ((tic) * SIGNIF) ? 0.0 : (x))
- #define NearlyEqual(x,y,tic) (fabs((x)-(y)) < ((tic) * SIGNIF))
-
- /* And the functions to map from user to terminal coordinates */
- #define map_x(x) (int)(x+0.5) /* maps floating point x to screen */
- #define map_y(y) (int)(y+0.5) /* same for y */
-
- /* And the functions to map from user 3D space into normalized -1..1 */
- #define map_x3d(x) ((x-x_min3d)*xscale3d-1.0)
- #define map_y3d(y) ((y-y_min3d)*yscale3d-1.0)
- #define map_z3d(z) ((z-floor_z)*zscale3d-1.0)
-
-
-
- /* Initialize the line style using the current device and set hidden styles */
- /* to it as well if hidden line removal is enabled. */
- static void setlinestyle(style)
- int style;
- {
- register struct termentry *t = term;
-
- (*t->linetype)(style);
-
- #ifndef LITE
- if (hidden3d) {
- hidden_line_type_above = style;
- hidden_line_type_below = style;
- }
- #endif /* LITE */
- }
-
- #ifndef LITE
- #endif /* not LITE */
-
-
-
- /* (DFK) For some reason, the Sun386i compiler screws up with the CheckLog
- * macro, so I write it as a function on that machine.
- *
- * Amiga SAS/C 6.2 thinks it will do too much work calling functions in
- * macro arguments twice, thus I inline theese functions. (MGR, 1993)
- */
- #if defined(sun386) || defined(AMIGA_SC_6_1)
- #ifdef AMIGA_SC_6_1
- __inline
- #endif
- static double
- CheckLog(is_log, base_log, x)
- TBOOLEAN is_log;
- double base_log;
- double x;
- {
- if (is_log)
- return(pow(base_log, x));
- else
- return(x);
- }
- #else
- /* (DFK) Use 10^x if logscale is in effect, else x */
- #define CheckLog(is_log, base_log, x) ((is_log) ? pow(base_log, (x)) : (x))
- #endif /* sun386 || SAS/C */
-
- static double
- LogScale(coord, is_log, log_base_log, what, axis)
- double coord; /* the value */
- TBOOLEAN is_log; /* is this axis in logscale? */
- double log_base_log; /* if so, the log of its base */
- char *what; /* what is the coord for? */
- char *axis; /* which axis is this for ("x" or "y")? */
- {
- if (is_log) {
- if (coord <= 0.0) {
- char errbuf[100]; /* place to write error message */
- (void) sprintf(errbuf,"%s has %s coord of %g; must be above 0 for log scale!",
- what, axis, coord);
- graph_error(errbuf);
- } else
- return(log(coord)/log_base_log);
- }
- return(coord);
- }
-
- /* And the functions to map from user 3D space to terminal coordinates */
- void map3d_xy(x, y, z, xt, yt)
- double x, y, z;
- unsigned int *xt, *yt;
- {
- int i,j;
- double v[4], res[4], /* Homogeneous coords. vectors. */
- w = trans_mat[3][3];
-
- v[0] = map_x3d(x); /* Normalize object space to -1..1 */
- v[1] = map_y3d(y);
- v[2] = map_z3d(z);
- v[3] = 1.0;
-
- for (i = 0; i < 2; i++) { /* Dont use the third axes (z). */
- res[i] = trans_mat[3][i]; /* Initiate it with the weight factor. */
- for (j = 0; j < 3; j++) res[i] += v[j] * trans_mat[j][i];
- }
-
- for (i = 0; i < 3; i++) w += v[i] * trans_mat[i][3];
- if (w == 0) w = 1e-5;
-
- *xt = (unsigned int) ((res[0] * xscaler / w) + xmiddle);
- *yt = (unsigned int) ((res[1] * yscaler / w) + ymiddle);
- }
-
-
-
- /* And the functions to map from user 3D space to terminal z coordinate */
- int map3d_z(x, y, z)
- double x, y, z;
- {
- int i, zt;
- double v[4], res, /* Homogeneous coords. vectors. */
- w = trans_mat[3][3];
-
- v[0] = map_x3d(x); /* Normalize object space to -1..1 */
- v[1] = map_y3d(y);
- v[2] = map_z3d(z);
- v[3] = 1.0;
-
- res = trans_mat[3][2]; /* Initiate it with the weight factor. */
- for (i = 0; i < 3; i++) res += v[i] * trans_mat[i][2];
- if(w==0) w= 1e-5;
- for (i = 0; i < 3; i++) w += v[i] * trans_mat[i][3];
- zt = ((int) (res * 16384 / w));
- return zt;
- }
-
- /* borders of plotting area */
- /* computed once on every call to do_plot */
- static void boundary3d(scaling,plots,count)
- TBOOLEAN scaling; /* TRUE if terminal is doing the scaling */
- struct surface_points *plots;
- int count;
- {
- register struct termentry *t = term;
- int ytlen, i;
-
- titlelin = 0;
-
- p_height= pointsize * t->v_tic;
- p_width = pointsize * t->h_tic;
- key_entry_height = pointsize * (t->v_tic) * 1.25;
- if (key_entry_height < (t->v_char) )
- key_entry_height = (t->v_char);
-
- /* count max_len key and number keys (plot-titles and contour labels) with len > 0 */
- max_ptitl_len = find_maxl_keys3d(plots,count,&ptitl_cnt);
- if ( (ytlen = label_width(key_title,&ktitle_lines)) > max_ptitl_len )
- max_ptitl_len = ytlen;
- key_col_wth = (max_ptitl_len + 4 ) * (t->h_char) + KEYWTH;
-
- /* luecken@udel.edu modifications
- sizes the plot to take up more of available resolution */
- if ( lmargin >= 0 )
- xleft = (t->h_char)*lmargin;
- else
- xleft = (t->h_char)*2 + (t->h_tic);
- xright = (scaling ? 1 : xsize) * (t->xmax) - (t->h_char)*2 - (t->h_tic);
- key_rows = ptitl_cnt;
- key_cols = 1;
- if (key == -1 && key_vpos == TUNDER ) {
- /* calculate max no cols, limited by label-length */
- key_cols = (int)(xright - xleft)/((max_ptitl_len + 4 ) * (t->h_char) + KEYWTH);
- key_rows = (int)(ptitl_cnt/key_cols)+((ptitl_cnt%key_cols)>0);
- /* now calculate actual no cols depending on no rows */
- key_cols = (int)(ptitl_cnt/key_rows)+((ptitl_cnt%key_rows)>0);
- key_col_wth = (int)(xright - xleft)/key_cols;
- /* key_rows += ktitle_lines; - messes up key - div */
- }
- /* this should also consider the view and number of lines in xformat || yformat || xlabel || ylabel */
- ybot = (t->v_char)*2.5 + 1; /* an absolute 1, with no terminal-dependent scaling ? */
- if (key_rows&&key_vpos==TUNDER)
- ybot += key_rows*key_entry_height + ktitle_lines*t->v_char;
-
- if (strlen(title.text)) {
- titlelin++;
- for(i=0;i<strlen(title.text);i++) {
- if (title.text[i] == '\\') titlelin++;
- }
- }
- ytop = (scaling ? 1 : ysize) * (t->ymax) - (t->v_char)*(titlelin+1.5) - 1;
- if (key == -1 && key_vpos != TUNDER ) {
- /* calculate max no rows, limited be ytop-ybot */
- i = (int)(ytop-ybot)/(t->v_char) - 1 - ktitle_lines;
- if (ptitl_cnt > i) {
- key_cols = (int)(ptitl_cnt/i)+((ptitl_cnt%i)>0);
- /* now calculate actual no rows depending on no cols */
- key_rows = (int)(ptitl_cnt/key_cols)+((ptitl_cnt%key_cols)>0);
- }
- key_rows += ktitle_lines;
- }
- if ( key_hpos == TOUT ) {
- xright -= key_col_wth*(key_cols-1) + key_col_wth - 2*(t->h_char);
- }
-
- xleft += t->xmax * xoffset;
- xright += t->xmax * xoffset;
- ytop += t->ymax * yoffset;
- ybot += t->ymax * yoffset;
- xmiddle = (xright + xleft) / 2;
- ymiddle = (ytop + ybot) / 2;
- xscaler = (xright - xleft) * 4 / 7;
- yscaler = (ytop - ybot) * 4 / 7;
- }
-
- #if 0
- /* not used ; anyway, should be done using bitshifts and squares,
- * rather than iteratively
- */
- static double dbl_raise(x,y)
- double x;
- int y;
- {
- register int i=ABS(y);
- double val=1.0;
- while (--i >= 0)
- val *= x;
- if (y < 0 ) return (1.0/val);
- return(val);
- }
- #endif
-
- /* we precalculate features of the key, to save lots of nested
- * ifs in code - x,y = user supplied or computed position of key
- * taken to be inner edge of a line sample
- */
- static int key_sample_left; /* offset from x for left of line sample */
- static int key_sample_right; /* offset from x for right of line sample */
- static int key_point_offset; /* offset from x for point sample */
- static int key_text_left; /* offset from x for left-justified text */
- static int key_text_right; /* offset from x for right-justified text */
- static int key_size_left; /* distance from x to left edge of box */
- static int key_size_right; /* distance from x to right edge of box */
-
-
-
- void do_3dplot(plots, pcount)
- struct surface_points *plots;
- int pcount; /* count of plots in linked list */
- {
- struct termentry *t = term;
- int surface;
- struct surface_points *this_plot = NULL;
- unsigned int xl, yl;
- int linetypeOffset = 0;
- double ztemp, temp;
- struct text_label *this_label;
- struct arrow_def *this_arrow;
- TBOOLEAN scaling;
- transform_matrix mat;
- int key_count;
- char ss[MAX_LINE_LEN+1], *s, *e;
-
- /* Initiate transformation matrix using the global view variables. */
- mat_rot_z(surface_rot_z, trans_mat);
- mat_rot_x(surface_rot_x, mat);
- mat_mult(trans_mat, trans_mat, mat);
- mat_scale(surface_scale / 2.0, surface_scale / 2.0, surface_scale / 2.0, mat);
- mat_mult(trans_mat, trans_mat, mat);
-
- /* modify min_z/max_z so it will zscale properly. */
- ztemp = (z_max3d - z_min3d) / (2.0 * surface_zscale);
- temp = (z_max3d + z_min3d) / 2.0;
- z_min3d = temp - ztemp;
- z_max3d = temp + ztemp;
-
- #if 0 /* already done in eval_3dplots */
- /* auto-extend ranges to tic-mark for autoscaled axes */
- if (xtics) setup_tics(FIRST_X_AXIS, &xticdef, xformat);
- if (ytics) setup_tics(FIRST_Y_AXIS, &yticdef, yformat);
- if (ztics) setup_tics(FIRST_Z_AXIS, &zticdef, zformat);
- #endif
-
- /* The extrema need to be set even when a surface is not being
- * drawn. Without this, gnuplot used to assume that the X and
- * Y axis started at zero. -RKC
- */
-
- if (polar)
- graph_error("Cannot splot in polar coordinate system.");
-
- /* done in plot3d.c
- * if (z_min3d == VERYLARGE || z_max3d == -VERYLARGE ||
- * x_min3d == VERYLARGE || x_max3d == -VERYLARGE ||
- * y_min3d == VERYLARGE || y_max3d == -VERYLARGE)
- * graph_error("all points undefined!");
- */
-
- /* If we are to draw the bottom grid make sure zmin is updated properly. */
- if (xtics || ytics || grid) {
- base_z = z_min3d - (z_max3d - z_min3d) * ticslevel;
- if (ticslevel >= 0)
- floor_z = base_z;
- else
- floor_z = z_min3d;
-
- if (ticslevel < -1)
- ceiling_z = base_z;
- else
- ceiling_z = z_max3d;
- } else {
- floor_z = base_z = z_min3d;
- ceiling_z = z_max3d;
- }
-
- /* This used be x_max3d == x_min3d, but that caused an infinite loop once. */
- if (fabs(x_max3d - x_min3d) < zero)
- graph_error("x_min3d should not equal x_max3d!");
- if (fabs(y_max3d - y_min3d) < zero)
- graph_error("y_min3d should not equal y_max3d!");
- if (fabs(z_max3d - z_min3d) < zero)
- graph_error("z_min3d should not equal z_max3d!");
-
- #ifndef LITE
- if (hidden3d) {
- struct surface_points *plot;
- int p=0;
- /* Verify data is hidden line removable - grid based. */
- for (plot = plots; ++p <= pcount; plot = plot->next_sp) {
- if (plot->plot_type == DATA3D && !plot->has_grid_topology){
- fprintf(stderr,"Notice: Cannot remove hidden lines from non grid data\n");
- return;
- }
-
- }
- }
- #endif /* not LITE */
-
- /* INITIALIZE TERMINAL */
- if (!term_init) {
- (*t->init)();
- term_init = TRUE;
- }
- screen_ok = FALSE;
- scaling = (*t->scale)(xsize, ysize);
-
- if (multiplot && term_graphics) {
- if (term_suspended && term->resume)
- (*t->resume)();
- term_suspended = FALSE;
- } else {
- (*t->graphics)();
- term_graphics = TRUE;
- }
-
- /* now compute boundary for plot (xleft, xright, ytop, ybot) */
- boundary3d(scaling,plots,pcount);
-
- /* SCALE FACTORS */
- zscale3d = 2.0/(ceiling_z - floor_z);
- yscale3d = 2.0/(y_max3d - y_min3d);
- xscale3d = 2.0/(x_max3d - x_min3d);
-
- (*t->linetype)(-2); /* border linetype */
-
- /* PLACE TITLE */
- if (*title.text != 0) {
- strcpy(ss, title.text);
- write_multiline( (unsigned int)((xleft+xright)/2+title.xoffset*t->h_char),
- (unsigned int)(ytop+(titlelin+title.yoffset)*(t->h_char)),
- ss, CENTRE, JUST_TOP, 0, title.font);
- }
-
- /* PLACE TIMEDATE */
- if (*timelabel.text) {
- char str[MAX_LINE_LEN+1];
- time_t now;
- unsigned int x = t->v_char + timelabel.xoffset * t->h_char;
- unsigned int y = yoffset*ymax + (timelabel.yoffset+1) * t->v_char;
-
- time(&now);
- strftime(str, MAX_LINE_LEN, timelabel.text, localtime(&now));
-
- if ((*t->text_angle)(1)) {
- write_multiline(x,y,str,CENTRE, JUST_TOP, 1, timelabel.font);
- (*t->text_angle)(0);
- } else {
- write_multiline(x,y,str,LEFT, JUST_BOT, 0, timelabel.font);
- }
- }
-
- /* PLACE LABELS */
- for (this_label = first_label; this_label!=NULL;
- this_label=this_label->next ) {
- unsigned int x,y;
-
- map_position(&this_label->place, &x, &y, "label");
- strcpy(ss, this_label->text);
- write_multiline( x,y, this_label->text, this_label->pos, CENTRE, 0, this_label->font);
- }
-
- /* PLACE ARROWS */
- for (this_arrow = first_arrow; this_arrow!=NULL;
- this_arrow = this_arrow->next ) {
- unsigned int sx,sy,ex,ey;
- map_position(&this_arrow->start, &sx, &sy, "arrow");
- map_position(&this_arrow->end, &ex, &ey, "arrow");
- (*t->linetype)(this_arrow->line);
- (*t->arrow)(sx, sy, ex, ey, this_arrow->head);
- }
-
- #ifndef LITE
- if (hidden3d && draw_surface) {
- init_hidden_line_removal();
- reset_hidden_line_removal();
- hidden_active = TRUE;
- }
- #endif /* not LITE */
-
- /* WORK OUT KEY SETTINGS AND DO KEY TITLE / BOX */
-
- if (key_reverse) {
- key_sample_left= -KEYWTH;
- key_sample_right= 0;
- key_text_left=t->h_char;
- key_text_right=(t->h_char)*(max_ptitl_len+1);
- key_size_right=(t->h_char)*(max_ptitl_len+2);
- key_size_left=(t->h_char) + KEYWTH;
- } else {
- key_sample_left= 0;
- key_sample_right= KEYWTH;
- key_text_left=-(t->h_char)*(max_ptitl_len+1);
- key_text_right=-(t->h_char);
- key_size_left=(t->h_char)*(max_ptitl_len+2);
- key_size_right=(t->h_char)+KEYWTH;
- }
- key_point_offset = (key_sample_left + key_sample_right)/2;
-
- if (key == -1) {
- if ( key_vpos == TUNDER ) {
- #if 0
- yl = yoffset * t->ymax + (key_rows) * key_entry_height + (ktitle_lines+2)*t->v_char;
- xl = max_ptitl_len * 1000/( KEYWTH/(t->h_char) + max_ptitl_len + 2);
- xl *= (xright - xleft)/key_cols;
- xl /= 1000;
- xl += xleft;
- #else
- /* maximise no cols, limited by label-length */
- key_cols = (int)(xright - xleft)/key_col_wth;
- key_rows = (int)(ptitl_cnt+key_cols-1)/key_cols;
- /* now calculate actual no cols depending on no rows */
- key_cols = (int)(ptitl_cnt+key_rows-1)/key_rows;
- key_col_wth = (int)(xright - xleft)/key_cols;
- /* we divide into columns, then centre in column by considering ratio
- * of key_left_size to key_right_size
- * key_size_left/(key_size_left+key_size_right) * (xright-xleft)/key_cols
- * do one integer division to maximise accuracy (hope we dont overflow !)
- */
- xl = xleft + ((xright-xleft)*key_size_left) / (key_cols*(key_size_left+key_size_right));
- yl = yoffset * t->ymax + (key_rows) * key_entry_height + (ktitle_lines+2)*t->v_char;
- #endif
- } else {
- if ( key_vpos == TTOP ) {
- yl = ytop - (t->v_tic) - t->v_char;
- } else {
- yl = ybot + (t->v_tic) + key_entry_height*key_rows + ktitle_lines*t->v_char;
- }
- if ( key_hpos == TOUT ) {
- /* keys outside plot border (right) */
- xl = xright + (t->h_tic) + key_size_left;
- } else if ( key_hpos == TLEFT ) {
- xl = xleft + (t->h_tic) + key_size_left;
- } else {
- xl = xright - key_size_right - key_col_wth*(key_cols-1);
- }
- }
- yl_ref = yl - ktitle_lines * (t->v_char);
- }
- if (key == 1) {
- map_position(&key_user_pos, &xl, &yl, "key");
- }
-
- if (key && key_box>-3) {
- int yt=yl;
- int yb=yl - key_entry_height*(key_rows-ktitle_lines) - ktitle_lines*t->v_char;
- int key_xr = xl + key_col_wth * (key_cols-1) + key_size_right;
- /* key_rows seems to contain title at this point ??? */
- (*t->linetype)(key_box);
- (*t->move)(xl-key_size_left,yb);
- (*t->vector)(xl-key_size_left,yt);
- (*t->vector)(key_xr,yt);
- (*t->vector)(key_xr,yb);
- (*t->vector)(xl-key_size_left,yb);
- /* draw a horizontal line between key title and first entry */ /* JFi */
- (*t->move)(xl-key_size_left,yt - (ktitle_lines) * t->v_char); /* JFi */
- (*t->vector)(xl+key_size_right,yt - (ktitle_lines) * t->v_char); /* JFi */
- }
-
- /* DRAW SURFACES AND CONTOURS */
-
- #ifndef LITE
- if (hidden3d && draw_surface) plot3d_hidden(plots,pcount);
- #endif /* not LITE */
- if (key != 0 && strlen(key_title)) {
- sprintf(ss,"%s\n",key_title);
- s = ss;
- yl -= t->v_char/2;
- while( (e=(char *)strchr(s,'\n')) != NULL ) {
- *e = '\0';
- if ( key_just == JLEFT) {
- (*t->justify_text)(LEFT);
- (*t->put_text)(xl+key_text_left,yl,s);
- } else {
- if ((*t->justify_text)(RIGHT)) {
- (*t->put_text)(xl+key_text_right,
- yl,s);
- } else {
- int x=xl+key_text_right-(t->h_char)*strlen(s);
- if (inrange(x,xleft, xright))
- (*t->put_text)(x,yl,s);
- }
- }
- s = ++e;
- yl -= t->v_char;
- }
- yl += t->v_char/2;
- }
- key_count = 0;
- yl_ref = yl -= key_entry_height/2; /* centralise the keys */
-
- this_plot = plots;
- for (surface = 0;
- surface < pcount;
- this_plot = this_plot->next_sp, surface++) {
- #ifndef LITE
- if ( hidden3d )
- hidden_no_update = FALSE;
- #endif /* not LITE */
-
- if (draw_surface) {
- (*t->linetype)(this_plot->line_type);
- #ifndef LITE
- if (hidden3d) {
- hidden_line_type_above = this_plot->line_type;
- hidden_line_type_below = this_plot->line_type + 1;
- }
- #endif /* not LITE */
- if (key != 0 && this_plot->title) {
- key_count++;
- key_text(xl, yl, this_plot->title);
- }
-
- switch(this_plot->plot_style) {
- case BOXES: /* can't do boxes in 3d yet so use impulses */
- case IMPULSES: {
- if (key != 0 && this_plot->title) {
- key_sample_line(xl,yl);
- }
- if (!(hidden3d && draw_surface))
- plot3d_impulses(this_plot);
- break;
- }
- case LINES: {
- if (key != 0 && this_plot->title) {
- key_sample_line(xl,yl);
- }
- if (!(hidden3d && draw_surface))
- plot3d_lines(this_plot);
- break;
- }
- case YERRORBARS: /* ignored; treat like points */
- case XERRORBARS: /* ignored; treat like points */
- case XYERRORBARS: /* ignored; treat like points */
- case POINTSTYLE: {
- if (key != 0 && this_plot->title
- && !clip_point(xl+key_point_offset,yl)) {
- key_sample_point(xl,yl,this_plot->point_type);
- }
- if (!(hidden3d && draw_surface))
- plot3d_points(this_plot);
- break;
- }
- case LINESPOINTS: {
- /* put lines */
- if (key != 0 && this_plot->title) {
- key_sample_line(xl,yl);
- }
- if (!(hidden3d && draw_surface))
- plot3d_lines(this_plot);
-
- /* put points */
- if (key != 0 && this_plot->title
- && !clip_point(xl+key_point_offset,yl)) {
- (*t->point)(xl+key_point_offset,yl,
- this_plot->point_type);
- }
- if (!(hidden3d && draw_surface))
- plot3d_points(this_plot);
- break;
- }
- case DOTS: {
- if (key != 0 && this_plot->title) {
- if (key == 1) {
- if (!clip_point(xl+key_point_offset,yl))
- (*t->point)(xl+key_point_offset,yl, -1);
- } else {
- (*t->point)(xl+key_point_offset,yl, -1);
- /* (*t->point)(xl+2*(t->h_char),yl, -1); */
- }
- }
- if (!(hidden3d && draw_surface))
- plot3d_dots(this_plot);
- break;
- }
- }
- if (key != 0 && this_plot->title) {
- if ( key_count >= key_rows ) {
- yl = yl_ref;
- xl += key_col_wth;
- key_count = 0;
- } else
- yl -= key_entry_height;
- }
- }
-
- #ifndef LITE
- if ( hidden3d ) {
- hidden_no_update = TRUE;
- hidden_line_type_above = this_plot->line_type + (hidden3d ? 2 : 1);
- hidden_line_type_below = this_plot->line_type + (hidden3d ? 2 : 1);
- }
- #endif /* not LITE */
-
- if (draw_contour && this_plot->contours != NULL) {
- struct gnuplot_contours *cntrs = this_plot->contours;
-
- (*t->linetype)(this_plot->line_type + (hidden3d ? 2 : 1));
- if (key != 0 && this_plot->title
- && !draw_surface && !label_contours) {
- key_count++;
- key_text(xl,yl, this_plot->title);
-
- switch(this_plot->plot_style) {
- case IMPULSES:
- case LINES:
- key_sample_line(xl,yl);
- break;
- case YERRORBARS: /* ignored; treat like points */
- case XERRORBARS: /* ignored; treat like points */
- case XYERRORBARS: /* ignored; treat like points */
- case POINTSTYLE:
- key_sample_point(xl,yl,this_plot->point_type);
- break;
- case LINESPOINTS:
- key_sample_line(xl,yl);
- break;
- case DOTS:
- key_sample_point(xl,yl,-1);
- break;
- }
- }
-
- linetypeOffset = this_plot->line_type + (hidden3d ? 2 : 1);
- while (cntrs) {
- if(label_contours && cntrs->isNewLevel) {
- (*t->linetype)(linetypeOffset++);
- if (key) {
- #ifndef LITE
- if(hidden3d) hidden_line_type_below = hidden_line_type_above = linetypeOffset-1;
- #endif /* not LITE */
- key_count++;
- key_text(xl,yl,cntrs->label);
-
- switch(this_plot->plot_style) {
- case IMPULSES:
- case LINES:
- case LINESPOINTS:
- key_sample_line(xl,yl);
- break;
- case YERRORBARS: /* ignored; treat like points */
- case XERRORBARS: /* ignored; treat like points */
- case XYERRORBARS: /* ignored; treat like points */
- case POINTSTYLE:
- key_sample_point(xl,yl,this_plot->point_type);
- break;
- case DOTS:
- key_sample_point(xl,yl,-1);
- break;
- } /* switch */
-
- if (key_count >= key_rows ) {
- yl = yl_ref;
- xl += key_col_wth;
- key_count = 0;
- } else /* might want to use t->v_char if not putting points in key - div */
- yl -= key_entry_height;
-
- } /* key */
- } /* label_contours */
- switch(this_plot->plot_style) {
- case IMPULSES:
- cntr3d_impulses(cntrs, this_plot);
- break;
- case LINES:
- cntr3d_lines(cntrs);
- break;
- case YERRORBARS: /* ignored; treat like points */
- case XERRORBARS: /* ignored; treat like points */
- case XYERRORBARS: /* ignored; treat like points */
- case POINTSTYLE:
- cntr3d_points(cntrs, this_plot);
- break;
- case LINESPOINTS:
- cntr3d_lines(cntrs);
- cntr3d_points(cntrs, this_plot);
- break;
- case DOTS:
- cntr3d_dots(cntrs);
- break;
- }
- cntrs = cntrs->next;
- }
- if (key != 0 && this_plot->title) {
- if (key_count >= key_rows ) {
- yl = yl_ref;
- xl += key_col_wth;
- key_count = 0;
- } else
- yl -= key_entry_height;
- }
- }
- }
-
- draw_bottom_grid(plots, pcount);
-
- if (!multiplot) {
- (*t->text)();
- term_graphics = FALSE;
- }
-
- (void) fflush(outfile);
-
- #ifndef LITE
- if (hidden3d && draw_surface) {
- term_hidden_line_removal();
- hidden_active = FALSE;
- }
- #endif /* not LITE */
- }
-
- /* plot3d_impulses:
- * Plot the surfaces in IMPULSES style
- */
- static void plot3d_impulses(plot)
- struct surface_points *plot;
- {
- int i; /* point index */
- unsigned int x,y,x0,y0; /* point in terminal coordinates */
- struct iso_curve *icrvs = plot->iso_crvs;
-
- while ( icrvs ) {
- struct coordinate GPHUGE *points = icrvs->points;
-
- for (i = 0; i < icrvs->p_count; i++) {
- switch (points[i].type)
- {
- case INRANGE:
- {
- map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
-
- if(inrange(0.0, min3d_z, max3d_z)){
- map3d_xy(points[i].x, points[i].y, 0.0, &x0, &y0);
- } else if(inrange(min3d_z, 0.0, points[i].z)){
- map3d_xy(points[i].x, points[i].y, min3d_z, &x0, &y0);
- } else {
- map3d_xy(points[i].x, points[i].y, max3d_z, &x0, &y0);
- }
-
- clip_move(x0,y0);
- clip_vector(x,y);
-
- break;
- }
- case OUTRANGE:
- {
- if(!inrange(points[i].x, x_min3d, x_max3d) ||
- !inrange(points[i].y, y_min3d, y_max3d))
- break;
-
- if(inrange(0.0, min3d_z, max3d_z))
- {
- /* zero point is INRANGE */
- map3d_xy(points[i].x, points[i].y, 0.0, &x0, &y0);
-
- /* must cross z=min3d_z or max3d_z limits */
- if(inrange(min3d_z, 0.0, points[i].z) &&
- min3d_z != 0.0 && min3d_z != points[i].z)
- {
- map3d_xy(points[i].x, points[i].y, min3d_z, &x, &y);
- }
- else
- {
- map3d_xy(points[i].x, points[i].y, max3d_z, &x, &y);
- }
- }
- else
- {
- /* zero point is also OUTRANGE */
- if(inrange(min3d_z, 0.0, points[i].z) &&
- inrange(max3d_z, 0.0, points[i].z))
- {
- /* crosses z=min3d_z or max3d_z limits */
- map3d_xy(points[i].x, points[i].y, max3d_z, &x, &y);
- map3d_xy(points[i].x, points[i].y, min3d_z, &x0, &y0);
- }
- else
- {
- /* doesn't cross z=min3d_z or max3d_z limits */
- break;
- }
- }
-
- clip_move(x0,y0);
- clip_vector(x,y);
-
- break;
- }
- default: /* just a safety */
- case UNDEFINED: {
- break;
- }
- }
- }
-
- icrvs = icrvs->next;
- }
- }
-
- /* plot3d_lines:
- * Plot the surfaces in LINES style
- */
- /* We want to always draw the lines in the same direction, otherwise when
- we draw an adjacent box we might get the line drawn a little differently
- and we get splotches. */
-
- #ifndef LITE
- #endif /* not LITE */
-
- static void plot3d_lines(plot)
- struct surface_points *plot;
- {
- int i;
- unsigned int x,y,x0,y0; /* point in terminal coordinates */
- double clip_x, clip_y, clip_z;
- struct iso_curve *icrvs = plot->iso_crvs;
- struct coordinate GPHUGE *points;
- enum coord_type prev = UNDEFINED;
- double lx[2], ly[2], lz[2]; /* two edge points */
-
- #ifndef LITE
- /* These are handled elsewhere. */
- if (plot->has_grid_topology && hidden3d)
- return;
- #endif /* not LITE */
-
- while (icrvs) {
- prev = UNDEFINED; /* type of previous plot */
-
- for(i = 0, points = icrvs->points; i < icrvs->p_count; i++) {
- switch (points[i].type) {
- case INRANGE: {
- map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
-
- if(prev == INRANGE)
- {
- clip_vector(x, y);
- }
- else
- {
- if(prev == OUTRANGE)
- {
- /* from outrange to inrange */
- if (!clip_lines1) {
- clip_move(x, y);
- }
- else {
- /*
- * Calculate intersection point and draw vector from there
- */
- edge3d_intersect(points, i, &clip_x, &clip_y, &clip_z);
-
- map3d_xy(clip_x, clip_y, clip_z, &x0, &y0);
-
- clip_move(x0,y0);
- clip_vector(x,y);
- }
- }
- else
- {
- clip_move(x,y);
- }
- }
-
- break;
- }
- case OUTRANGE:{
- if(prev == INRANGE)
- {
- /* from inrange to outrange */
- if (clip_lines1) {
- /*
- * Calculate intersection point and draw vector to it
- */
-
- edge3d_intersect(points, i, &clip_x, &clip_y, &clip_z);
-
- map3d_xy(clip_x, clip_y, clip_z, &x0, &y0);
-
- clip_vector(x0,y0);
- }
- }
- else if (prev == OUTRANGE)
- {
- /* from outrange to outrange */
- if (clip_lines2) {
- /*
- * Calculate the two 3D intersection points if present
- */
- if (two_edge3d_intersect(points, i, lx, ly, lz)) {
-
- map3d_xy(lx[0], ly[0], lz[0], &x, &y);
-
- map3d_xy(lx[1], ly[1], lz[1], &x0, &y0);
-
- clip_move(x, y);
- clip_vector(x0, y0);
- }
- }
- }
-
- break;
- }
- case UNDEFINED: {
- break;
- default: graph_error("Unknown point type in plot3d_lines");
- }
- }
-
- prev = points[i].type;
- }
-
- icrvs = icrvs->next;
- }
- }
-
- /* plot3d_points:
- * Plot the surfaces in POINTSTYLE style
- */
- static void plot3d_points(plot)
- struct surface_points *plot;
- {
- int i;
- unsigned x,y;
- struct termentry *t = term;
- struct iso_curve *icrvs = plot->iso_crvs;
-
- while ( icrvs ) {
- struct coordinate GPHUGE *points = icrvs->points;
-
- for (i = 0; i < icrvs->p_count; i++) {
- if (points[i].type == INRANGE) {
- map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
-
- if (!clip_point(x,y))
- (*t->point)(x,y, plot->point_type);
- }
- }
-
- icrvs = icrvs->next;
- }
- }
-
- /* plot3d_dots:
- * Plot the surfaces in DOTS style
- */
- static void plot3d_dots(plot)
- struct surface_points *plot;
- {
- int i;
- struct termentry *t = term;
- struct iso_curve *icrvs = plot->iso_crvs;
-
- while ( icrvs ) {
- struct coordinate GPHUGE *points = icrvs->points;
-
- for (i = 0; i < icrvs->p_count; i++) {
- unsigned int x,y;
- map3d_xy(points[i].x, points[i].y, points[i].z, &x, &y);
-
- if (!clip_point(x,y))
- (*t->point)(x,y, -1);
- }
-
- icrvs = icrvs->next;
- }
- }
-
- /* cntr3d_impulses:
- * Plot a surface contour in IMPULSES style
- */
- static void cntr3d_impulses(cntr, plot)
- struct gnuplot_contours *cntr;
- struct surface_points *plot;
- {
- int i; /* point index */
- unsigned int x,y,x0,y0; /* point in terminal coordinates */
-
- if (draw_contour & CONTOUR_SRF) {
- for (i = 0; i < cntr->num_pts; i++) {
- map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
- &x, &y);
- map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
- &x0, &y0);
-
- clip_move(x0,y0);
- clip_vector(x,y);
- }
- }
- else
- cntr3d_points(cntr, plot); /* Must be on base grid, so do points. */
- }
-
- /* cntr3d_lines:
- * Plot a surface contour in LINES style
- */
- static void cntr3d_lines(cntr)
- struct gnuplot_contours *cntr;
- {
- int i; /* point index */
- unsigned int x,y; /* point in terminal coordinates */
-
- if (draw_contour & CONTOUR_SRF) {
- for (i = 0; i < cntr->num_pts; i++) {
- map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
- &x, &y);
-
- if (i > 0) {
- clip_vector(x,y);
- if(i == 1) suppressMove = TRUE;
- } else {
- clip_move(x,y);
- }
- }
- }
- suppressMove = FALSE; /* beginning a new contour level, so moveto() required */
-
- if (draw_contour & CONTOUR_BASE) {
- for (i = 0; i < cntr->num_pts; i++) {
- map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
- &x, &y);
-
- if (i > 0) {
- clip_vector(x,y);
- if(i == 1) suppressMove = TRUE;
- } else {
- clip_move(x,y);
- }
- }
- }
- suppressMove = FALSE; /* beginning a new contour level, so moveto() required */
- }
-
- /* cntr3d_points:
- * Plot a surface contour in POINTSTYLE style
- */
- static void cntr3d_points(cntr, plot)
- struct gnuplot_contours *cntr;
- struct surface_points *plot;
- {
- int i;
- unsigned int x,y;
- struct termentry *t = term;
-
- if (draw_contour & CONTOUR_SRF) {
- for (i = 0; i < cntr->num_pts; i++) {
- map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
- &x, &y);
-
- if (!clip_point(x,y))
- (*t->point)(x,y, plot->point_type);
- }
- }
-
- if (draw_contour & CONTOUR_BASE) {
- for (i = 0; i < cntr->num_pts; i++) {
- map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
- &x, &y);
-
- if (!clip_point(x,y))
- (*t->point)(x,y, plot->point_type);
- }
- }
- }
-
- /* cntr3d_dots:
- * Plot a surface contour in DOTS style
- */
- static void cntr3d_dots(cntr)
- struct gnuplot_contours *cntr;
- {
- int i;
- unsigned int x,y;
- struct termentry *t = term;
-
- if (draw_contour & CONTOUR_SRF) {
- for (i = 0; i < cntr->num_pts; i++) {
- map3d_xy(cntr->coords[i].x, cntr->coords[i].y, cntr->coords[i].z,
- &x, &y);
-
- if (!clip_point(x,y))
- (*t->point)(x,y, -1);
- }
- }
-
- if (draw_contour & CONTOUR_BASE) {
- for (i = 0; i < cntr->num_pts; i++) {
- map3d_xy(cntr->coords[i].x, cntr->coords[i].y, base_z,
- &x, &y);
-
- if (!clip_point(x,y))
- (*t->point)(x,y, -1);
- }
- }
- }
-
-
-
- /* map xmin | xmax to 0 | 1 and same for y
- * 0.1 avoids any rounding errors
- */
- #define MAP_HEIGHT_X(x) ( (int) (((x)-x_min3d)/(x_max3d-x_min3d)+0.1) )
- #define MAP_HEIGHT_Y(y) ( (int) (((y)-y_min3d)/(y_max3d-y_min3d)+0.1) )
-
- /* if point is at corner, update height[][] and depth[][]
- * we are still assuming that extremes of surfaces are at corners,
- * but we are not assuming order of corners
- */
- static void check_corner_height(p,height,depth)
- struct coordinate GPHUGE *p;
- double height[2][2];
- double depth[2][2];
- {
- if (p->type != INRANGE) return;
- if ( (fabs(p->x - x_min3d)<zero || fabs(p->x - x_max3d)<zero) &&
- (fabs(p->y - y_min3d)<zero || fabs(p->y - y_max3d)<zero)) {
- unsigned int x= MAP_HEIGHT_X(p->x);
- unsigned int y= MAP_HEIGHT_Y(p->y);
- if (height[x][y] < p->z)
- height[x][y] = p->z;
- if (depth[x][y] > p->z)
- depth[x][y] = p->z;
- }
- }
-
-
- /* Draw the bottom grid that hold the tic marks for 3d surface. */
- static void draw_bottom_grid(plot, plot_num)
- struct surface_points *plot;
- int plot_num;
- {
- unsigned int x,y; /* point in terminal coordinates */
- struct termentry *t = term;
- char ss[MAX_LINE_LEN+1];
-
- /* work out where the axes and tics are drawn */
-
- {
- int quadrant=surface_rot_z/90;
- if ( (quadrant+1)&2) {
- zaxis_x = x_max3d;
- xaxis_y = y_max3d;
- } else {
- zaxis_x = x_min3d;
- xaxis_y = y_min3d;
- }
-
- if (quadrant&2) {
- zaxis_y = y_max3d;
- yaxis_x = x_min3d;
- } else {
- zaxis_y = y_min3d;
- yaxis_x = x_max3d;
- }
-
- if (surface_rot_x > 90) {
- /* labels on the back axes */
- back_x = yaxis_x = x_min3d + x_max3d - yaxis_x;
- back_y = xaxis_y = y_min3d + y_max3d - xaxis_y;
- } else {
- back_x = x_min3d + x_max3d - yaxis_x;
- back_y = y_min3d + y_max3d - xaxis_y;
- }
- }
-
- if (draw_border) {
- unsigned int bl_x, bl_y; /* bottom left */
- unsigned int bb_x, bb_y; /* bottom back */
- unsigned int br_x, br_y; /* bottom right */
- unsigned int bf_x, bf_y; /* bottom front */
- #ifndef LITE
- int save_update=hidden_no_update;
- hidden_no_update=TRUE;
- #endif /* LITE */
- setlinestyle(-2);
-
- map3d_xy(zaxis_x, zaxis_y, base_z, &bl_x, &bl_y);
- map3d_xy( back_x, back_y, base_z, &bb_x, &bb_y);
- map3d_xy(x_min3d+x_max3d-zaxis_x, y_min3d+y_max3d-zaxis_y, base_z, &br_x, &br_y);
- map3d_xy(x_min3d+x_max3d-back_x, y_min3d+y_max3d-back_y, base_z, &bf_x, &bf_y);
-
- /* border around base */
- {
- int save=hidden_active;
- hidden_active=FALSE; /* this is in front */
- if (draw_border&4) draw_clip_line(br_x, br_y, bf_x, bf_y);
- if (draw_border&1) draw_clip_line(bl_x, bl_y, bf_x, bf_y);
- hidden_active=save;
- }
- if (draw_border&2) draw_clip_line(bl_x, bl_y, bb_x, bb_y);
- if (draw_border&8) draw_clip_line(br_x, br_y, bb_x, bb_y);
-
- if ( draw_surface || (draw_contour&CONTOUR_SRF)) {
- int save=hidden_active;
- /* map the 8 corners to screen */
- unsigned int fl_x, fl_y; /* floor left */
- unsigned int fb_x, fb_y; /* floor back */
- unsigned int fr_x, fr_y; /* floor right */
- unsigned int ff_x, ff_y; /* floor front */
-
- unsigned int tl_x, tl_y; /* top left */
- unsigned int tb_x, tb_y; /* top back */
- unsigned int tr_x, tr_y; /* top right */
- unsigned int tf_x, tf_y; /* top front */
-
- map3d_xy(zaxis_x, zaxis_y, floor_z, &fl_x, &fl_y);
- map3d_xy( back_x, back_y, floor_z, &fb_x, &fb_y);
- map3d_xy(x_min3d+x_max3d-zaxis_x, y_min3d+y_max3d-zaxis_y, floor_z, &fr_x, &fr_y);
- map3d_xy(x_min3d+x_max3d-back_x, y_min3d+y_max3d-back_y, floor_z, &ff_x, &ff_y);
-
- map3d_xy(zaxis_x, zaxis_y, ceiling_z, &tl_x, &tl_y);
- map3d_xy( back_x, back_y, ceiling_z, &tb_x, &tb_y);
- map3d_xy(x_min3d+x_max3d-zaxis_x, y_min3d+y_max3d-zaxis_y, ceiling_z, &tr_x, &tr_y);
- map3d_xy(x_min3d+x_max3d-back_x, y_min3d+y_max3d-back_y, ceiling_z, &tf_x, &tf_y);
-
- /* vertical lines, to surface or to very top */
- if ( (draw_border & 0xf0)==0xf0) {
- /* all four verticals drawn - save some time */
- draw_clip_line(fl_x, fl_y, tl_x, tl_y);
- draw_clip_line(fb_x, fb_y, tb_x, tb_y);
- draw_clip_line(fr_x, fr_y, tr_x, tr_y);
- hidden_active=FALSE; /* this is in front */
- draw_clip_line(ff_x, ff_y, tf_x, tf_y);
- hidden_active=save;
- } else {
- /* search surfaces for heights at corners */
- double height[2][2];
- double depth[2][2];
- unsigned int zaxis_i=MAP_HEIGHT_X(zaxis_x);
- unsigned int zaxis_j=MAP_HEIGHT_Y(zaxis_y);
- unsigned int back_i=MAP_HEIGHT_X(back_x);
- int back_j=MAP_HEIGHT_Y(back_y);
-
- height[0][0]=height[0][1]=height[1][0]=height[1][1]=base_z;
- depth[0][0]=depth[0][1]=depth[1][0]=depth[1][1]=base_z;
-
- for (; --plot_num >= 0; plot=plot->next_sp) {
- struct iso_curve *curve=plot->iso_crvs;
- int count=curve->p_count;
- int iso;
- if (plot->plot_type==DATA3D) {
- if (!plot->has_grid_topology) continue;
- iso=plot->num_iso_read;
- } else
- iso=iso_samples_2;
-
- check_corner_height(curve->points, height, depth);
- check_corner_height(curve->points+count-1, height, depth);
- while (--iso)
- curve=curve->next;
- check_corner_height(curve->points, height, depth);
- check_corner_height(curve->points+count-1, height, depth);
- }
-
- #define VERTICAL(mask, x,y,i,j,bx,by,tx,ty) \
- if (draw_border&mask) \
- draw_clip_line(bx,by,tx,ty);\
- else if (height[i][j]!=depth[i][j]) \
- { unsigned int a0,b0, a1, b1; \
- map3d_xy(x,y,depth[i][j],&a0,&b0); \
- map3d_xy(x,y,height[i][j],&a1,&b1); \
- draw_clip_line(a0,b0,a1,b1); \
- }
-
- VERTICAL(16, zaxis_x, zaxis_y, zaxis_i, zaxis_j,fl_x, fl_y, tl_x, tl_y)
- VERTICAL(32, back_x, back_y, back_i, back_j,fb_x, fb_y, tb_x, tb_y)
- VERTICAL(64, x_min3d+x_max3d-zaxis_x, y_min3d+y_max3d-zaxis_y, 1-zaxis_i, 1-zaxis_j,fr_x, fr_y, tr_x, tr_y)
- hidden_active=FALSE;
- VERTICAL(128, x_min3d+x_max3d-back_x, y_min3d+y_max3d-back_y, 1-back_i, 1-back_j,ff_x, ff_y, tf_x, tf_y)
- hidden_active=save;
- }
-
- /* now border lines on top */
- if (draw_border&256) draw_clip_line(tl_x, tl_y, tb_x, tb_y);
- if (draw_border&512) draw_clip_line(tr_x, tr_y, tb_x, tb_y);
- /* these lines are in front of surface (?) */
- hidden_active=FALSE;
- if (draw_border&1024) draw_clip_line(tl_x, tl_y, tf_x, tf_y);
- if (draw_border&2048) draw_clip_line(tr_x, tr_y, tf_x, tf_y);
- hidden_active=save;
- }
- #ifndef LITE
- hidden_no_update=save_update;
- #endif /* LITE */
- }
-
- if (xtics || *xlabel.text) {
- unsigned int x0,y0,x1,y1;
- double mid_x = (x_max3d+x_min3d)/2;
- double len;
- map3d_xy(mid_x, xaxis_y, base_z, &x0, &y0);
- map3d_xy(mid_x, y_min3d + y_max3d - xaxis_y, base_z, &x1, &y1);
- { /* take care over unsigned quantities */
- int dx = x1-x0;
- int dy = y1-y0;
- len=sqrt((double)(dx*dx+dy*dy));
- tic_unitx = dx/len;
- tic_unity = dy/len;
- }
-
- if (xtics) {
- gen_tics(FIRST_X_AXIS, &xticdef,grid&(GRID_X|GRID_MX),mxtics,mxtfreq, xtick_callback);
- }
-
- if (*xlabel.text) {
- /* label at xaxis_y + 1/4 of (xaxis_y-other_y) */
- double step = (2*xaxis_y-y_max3d-y_min3d)/4;
- map3d_xy(mid_x, xaxis_y+step, base_z,&x1,&y1);
- x1 += xlabel.xoffset * t->h_char;
- y1 += xlabel.yoffset * t->v_char;
- if (!tic_in) {
- x1 -= tic_unitx*ticscale*(t->h_tic);
- y1 -= tic_unity*ticscale*(t->v_tic);
- }
- strcpy(ss, xlabel.text); /* write_multiline mods it */
- write_multiline(x1,y1,ss, CENTRE, JUST_TOP,0, xlabel.font);
- }
- }
-
- if (ytics || *ylabel.text) {
- unsigned int x0,y0,x1,y1;
- double mid_y = (y_max3d+y_min3d)/2;
- double len;
- map3d_xy(yaxis_x, mid_y, base_z, &x0, &y0);
- map3d_xy(x_min3d + x_max3d - yaxis_x, mid_y, base_z, &x1, &y1);
- { /* take care over unsigned quantities */
- int dx = x1-x0;
- int dy = y1-y0;
- len=sqrt((double)(dx*dx+dy*dy));
- tic_unitx = dx/len;
- tic_unity = dy/len;
- }
- if (ytics) {
- gen_tics(FIRST_Y_AXIS, &yticdef,grid&(GRID_Y|GRID_MY),mytics,mytfreq, ytick_callback);
- }
-
- if (*ylabel.text) {
- double step = (x_max3d+x_min3d-2*yaxis_x)/4;
- map3d_xy(yaxis_x-step, mid_y, base_z,&x1,&y1);
- x1 += ylabel.xoffset * t->h_char;
- y1 += ylabel.yoffset * t->v_char;
- if (!tic_in) {
- x1 -= tic_unitx*ticscale*(t->h_tic);
- y1 -= tic_unity*ticscale*(t->v_tic);
- }
- strcpy(ss, ylabel.text); /* write_multiline mods it */
- write_multiline(x1,y1,ss, CENTRE, JUST_TOP,0, ylabel.font);
- }
- }
-
- /* do z tics */
-
- if (ztics && (draw_surface || (draw_contour&CONTOUR_SRF))) {
- gen_tics(FIRST_Z_AXIS, &zticdef, grid&(GRID_Z|GRID_MZ), mztics, mztfreq, ztick_callback);
- }
-
- if ( (xzeroaxis>=-2) && !is_log_y && inrange(0,y_min3d, y_max3d)) {
- unsigned int x,y,x1,y1;
- (*t->linetype)(xzeroaxis);
- map3d_xy(x_min3d, 0.0, base_z, &x, &y);
- map3d_xy(x_max3d, 0.0, base_z, &x1, &y1);
- draw_clip_line(x,y,x1,y1);
- }
- if ((yzeroaxis>=-2) && !is_log_x && inrange(0,x_min3d, x_max3d)) {
- unsigned int x,y,x1,y1;
- (*t->linetype)(yzeroaxis);
- map3d_xy(0.0, y_min3d, base_z, &x, &y);
- map3d_xy(0.0, y_max3d, base_z, &x1, &y1);
- draw_clip_line(x,y,x1,y1);
- }
-
- /* PLACE ZLABEL - along the middle grid Z axis - eh ? */
- if (*zlabel.text && (draw_surface || (draw_contour & CONTOUR_SRF))) {
- map3d_xy(zaxis_x,zaxis_y,z_max3d + (z_max3d-base_z)/4, &x, &y);
-
- x += zlabel.xoffset * t->h_char;
- y += zlabel.yoffset * t->v_char;
-
- strcpy(ss, zlabel.text);
- write_multiline(x,y,ss,CENTRE, CENTRE, 0, zlabel.font);
-
- }
- }
-
-
- static void xtick_callback(axis,place,text,grid)
- int axis;
- double place;
- char *text;
- int grid; /* linetype or -2 for none */
- {
- unsigned int x,y,x1,y1;
- double scale=(text?ticscale:miniticscale);
- int dirn=tic_in?1:-1;
- register struct termentry *t = term;
- map3d_xy(place, xaxis_y, base_z, &x, &y);
- if (grid > -2) {
- (*t->linetype)(grid);
- /* to save mapping twice, map non-axis y */
- map3d_xy(place, y_min3d+y_max3d-xaxis_y, base_z, &x1, &y1);
- draw_clip_line(x,y,x1,y1);
- (*t->linetype)(-2);
- }
- if (xtics&TICS_ON_AXIS) {
- map3d_xy(place, (y_min3d+y_max3d)/2, base_z, &x, &y);
- }
- x1=x+tic_unitx*scale*(t->h_tic)*dirn;
- y1=y+tic_unity*scale*(t->v_tic)*dirn;
- draw_clip_line(x,y,x1,y1);
- if (text) {
- int just;
- if (tic_unitx < -0.9)
- just=LEFT;
- else if (tic_unitx < 0.9)
- just=CENTRE;
- else
- just=RIGHT;
- x1=x-tic_unitx*(t->h_tic)*2;
- y1=y-tic_unity*(t->v_tic)*2;
- if (!tic_in) {
- x1 -= tic_unitx*(t->h_tic)*ticscale;
- y1 -= tic_unity*(t->v_tic)*ticscale;
- }
- clip_put_text_just(x1,y1,text,just);
- }
- if (xtics & TICS_MIRROR) {
- map3d_xy(place, y_min3d + y_max3d - xaxis_y, base_z, &x, &y);
- x1=x-tic_unitx*scale*(t->h_tic)*dirn;
- y1=y-tic_unity*scale*(t->v_tic)*dirn;
- draw_clip_line(x,y,x1,y1);
- }
- }
-
- static void ytick_callback(axis,place,text,grid)
- int axis;
- double place;
- char *text;
- int grid;
- {
- unsigned int x,y,x1,y1;
- double scale=(text?ticscale:miniticscale);
- int dirn=tic_in?1:-1;
- register struct termentry *t = term;
- map3d_xy(yaxis_x, place, base_z, &x, &y);
- if (grid > -2) {
- (*t->linetype)(grid);
- map3d_xy(x_min3d+x_max3d-yaxis_x, place, base_z, &x1, &y1);
- draw_clip_line(x,y,x1,y1);
- (*t->linetype)(-2);
- }
- if (ytics&TICS_ON_AXIS) {
- map3d_xy( (x_min3d+x_max3d)/2, place, base_z, &x, &y);
- }
- x1=x+tic_unitx*scale*dirn*(t->h_tic);
- y1=y+tic_unity*scale*dirn*(t->v_tic);
- draw_clip_line(x,y,x1,y1);
- if (text) {
- int just;
- if (tic_unitx < -0.9)
- just=LEFT;
- else if (tic_unitx < 0.9)
- just=CENTRE;
- else
- just=RIGHT;
- x1=x-tic_unitx*(t->h_tic)*2;
- y1=y-tic_unity*(t->v_tic)*2;
- if (!tic_in) {
- x1 -= tic_unitx*(t->h_tic)*ticscale;
- y1 -= tic_unity*(t->v_tic)*ticscale;
- }
- clip_put_text_just(x1,y1,text,just);
- }
- if (ytics & TICS_MIRROR) {
- map3d_xy(x_min3d + x_max3d - yaxis_x, place, base_z, &x, &y);
- x1=x-tic_unitx*scale*(t->h_tic)*dirn;
- y1=y-tic_unity*scale*(t->v_tic)*dirn;
- draw_clip_line(x,y,x1,y1);
- }
- }
-
- static void ztick_callback(axis,place,text,grid)
- int axis;
- double place;
- char *text;
- int grid;
- {
- int len=(text?ticscale:miniticscale)*(tic_in?1:-1)*term->h_tic;
- unsigned int x,y;
- register struct termentry *t = term;
- if (grid > -2) {
- unsigned int x1,y1,x2,y2,x3,y3;
- double other_x=x_min3d+x_max3d-zaxis_x;
- double other_y=y_min3d+y_max3d-zaxis_y;
- (*t->linetype)(grid);
- map3d_xy(zaxis_x, zaxis_y, place, &x1, &y1);
- map3d_xy(back_x, back_y, place, &x2, &y2);
- map3d_xy(other_x, other_y, place, &x3, &y3);
- draw_clip_line(x1,y1,x2,y2);
- draw_clip_line(x2,y2,x3,y3);
- (*t->linetype)(-2);
- }
- map3d_xy(zaxis_x, zaxis_y, place, &x, &y);
- draw_clip_line(x,y,x+len, y);
- if (text) {
- int x1=x-term->h_tic*2;
- if (!tic_in)
- x1 -= term->h_tic*ticscale;
- clip_put_text_just(x1,y,text,RIGHT);
- }
- if (ztics & TICS_MIRROR) {
- double other_x = x_min3d + x_max3d - zaxis_x;
- double other_y = y_min3d + y_max3d - zaxis_y;
- map3d_xy(other_x, other_y, place, &x, &y);
- draw_clip_line(x,y,x-len, y);
- }
- }
-
-
- static void map_position(pos, x, y, what)
- struct position *pos;
- unsigned int *x, *y;
- char *what;
- {
-
- double xpos=pos->x;
- double ypos=pos->y;
- double zpos=pos->z;
- int screens=0; /* need either 0 or 3 screen co-ordinates */
-
- switch(pos->scalex) {
- case first_axes:
- case second_axes:
- xpos = LogScale(xpos, is_log_x, log_base_log_x, what, "x");
- break;
- case graph:
- xpos=min_array[FIRST_X_AXIS]+xpos*(max_array[FIRST_X_AXIS]-min_array[FIRST_X_AXIS]);
- break;
- case screen:
- ++screens;
- }
-
- switch(pos->scaley) {
- case first_axes:
- case second_axes:
- ypos = LogScale(ypos, is_log_y, log_base_log_y, what, "y");
- break;
- case graph:
- ypos=min_array[FIRST_Y_AXIS]+ypos*(max_array[FIRST_Y_AXIS]-min_array[FIRST_Y_AXIS]);
- break;
- case screen:
- ++screens;
- }
-
- switch(pos->scalez) {
- case first_axes:
- case second_axes:
- zpos = LogScale(zpos, is_log_z, log_base_log_z, what, "z");
- break;
- case graph:
- zpos=min_array[FIRST_Z_AXIS]+zpos*(max_array[FIRST_Z_AXIS]-min_array[FIRST_Z_AXIS]);
- break;
- case screen:
- ++screens;
- }
-
- if (screens==0) {
- map3d_xy(xpos,ypos,zpos, x,y);
- return;
- }
-
- if (screens != 3) {
- graph_error("Cannot mix screen co-ordinates with other types");
- }
-
- {
- register struct termentry *t = term;
- *x = pos->x*(t->xmax) + 0.5;
- *y = pos->y*(t->ymax) + 0.5;
- }
-
- return;
- }
-
-
-
- static void key_text(xl, yl, text)
- int xl, yl;
- char *text;
- {
- if ( key_just == JLEFT && key == -1 ) {
- (*term->justify_text)(LEFT);
- (*term->put_text)(xl+key_text_left, yl,text);
- } else {
- if ((*term->justify_text)(RIGHT)) {
- if ( key == 1 )
- clip_put_text(xl+key_text_right,yl,text);
- else
- (*term->put_text)(xl+key_text_right,yl,text);
- } else {
- int x=xl+key_text_right-(term->h_char)*strlen(text);
- if (key == 1) {
- if (i_inrange(x, xleft, xright))
- clip_put_text(x,yl,text);
- } else {
- (*term->put_text)(x,yl,text);
- }
- }
- }
- }
-
- static void key_sample_line(xl, yl)
- int xl, yl;
- {
- if (key == -1) {
- (*term->move)(xl+key_sample_left,yl);
- (*term->vector)(xl+key_sample_right,yl);
- } else {
- clip_move(xl+key_sample_left,yl);
- clip_vector(xl+key_sample_right,yl);
- }
- }
-
- static void key_sample_point(xl, yl, pointtype)
- int xl, yl;
- int pointtype;
- {
- if (!clip_point(xl+key_point_offset,yl)) {
- (*term->point)(xl+key_point_offset,yl, pointtype);
- } else {
- (*term->point)(xl+key_point_offset,yl, pointtype);
- }
- }
-
-